Estoy sondeando largamente la ruta node.js con la solicitud ajax de JQuery (xhr). Esto envía una solicitud GET a mi servidor Express y escucha los eventos del bus de mensajes. Estoy configurando un tiempo de espera en esa solicitud GET (ya que mi proxy eliminaría las solicitudes largas). Entonces, después del tiempo de espera, el cliente debe enviar un evento de cancelación al servidor.
Quiero capturar ese evento de cancelación/cierre/finalización y eliminar el oyente/suscriptor del bus de mensajes relevante.
Pero lucho. Probé req.on("close"..) y el módulo npm terminado, pero eso no funcionó para mí. Tampoco soy mucho más inteligente después de leer la documentación http del nodo: https://nodejs.org/api/http.html .
¿Alguna idea de cómo hacer frente a esta bestia? ¿O mejores formas de eliminar a los oyentes para evitar pérdidas de memoria?
Elementos esenciales del lado del servidor:
// server.js var express = require("express"); var EventEmitter = require("events").EventEmitter; var messageBus = new EventEmitter(); messageBus.setMaxListeners(20); var REST_PORT = (process.env.PORT || 5000); var app = express(); app.get("/events", (req, res) => { var listener = function(res) { messageBus.once("message", function(data) { res.status(200).json(data); }); }; req.on("abort", function() { //I tried also "aborted", "close", "closed", "finish", "finished"..no luck messageBus.removeListener("message", listener); }); listener(res); console.log("Total listeners to 'message' events:", messageBus.listeners("message").length); }); // other messageBus.emit logic .. app.listen(REST_PORT, () => { console.log("Application ready on port " + REST_PORT); });Elementos esenciales del lado del cliente:
//client.js $.ajax({ method: "GET", async: true, url: "/events", success: function(data) { callback(data); }, complete: function(request, status, err) { if (status == "timeout" || status == "success") { console.log("LOG: Normal long-polling timeout or successful poll, continuing."); longPoll(); } else { console.warn("WARN: Server probably offline, retrying in 2 sec."); setTimeout(function() { longPoll(); }, 2000); } }, timeout: 30000 });¡Gracias!
Si esto ayuda a alguien, finalmente decidí implementar el sondeo largo de manera diferente y eliminar la solicitud del cliente en el lado del servidor después de cierto tiempo de espera. Esto me funciona muy bien y, después de reflexionar, es probablemente un mejor mecanismo que confiar en que el cliente cierre las solicitudes correctamente.
setTimeout(() => { if (!responded) { messageBus.removeListener("message", listener); res.status(204).end(); } }, 30000);Recomiendo abortar su sistema de sondeo largo personalizado por completo y usar uno de los sistemas de mensajería/tipo socket existentes. Hay muchos que están completamente formados. socket.io sigue siendo el más popular y funciona bien, pero algunas alternativas como estas podrían ser mejores https://www.reddit.com/r/node/comments/4ktqae/socketio_alternatives/